<template>
	<div class="tool-bar-ri h-full">
		<div class="header-icon">
			<div class="model-ningsi" @click="showModel">凝思大模型</div>
			<el-link type="primary" :href="API_URL" target="_blank" class="m-4"> {{ $t("toolbarright.link") }} </el-link>
			<AssemblySize v-if="false" />
			<Language id="language" v-if="false" />
			<ThemeSetting id="themeSetting" />
			<Message id="message" />
		</div>
		<Avatar />
		<div class="ningsiModel" v-if="state.modelShow">
			<div class="ningsiModel-title">
				<span class="title">聊天</span>
				<div class="chat-type">
					<span>对话模式：</span>
					<el-select v-model="state.modelType" placeholder="Select" style="width: 150px">
						<el-option v-for="item in state.modelOptions" :key="item.value" :label="item.label" :value="item.value" />
					</el-select>
				</div>

				<span class="close" @click="closeModel">关闭</span>
			</div>
			<div class="chat-content">
				<div
					v-show="state.answerList.length"
					v-for="item in state.answerList"
					class="answerList-item"
					:key="item.time"
					:class="item.type == 'answer' ? 'answerList-left' : 'answerList-right'"
				>
					<div class="answerList-title">
						<span class="answer-avatar">{{ item.type == "answer" ? "ans" : "que" }}</span>
						<span class="answer-time">{{ item.time }}</span>
					</div>
					<div class="answer-text">
						<span v-html="markdown.render(item.content)"></span>
					</div>
				</div>
				<div
					v-show="!state.answerList.length"
					v-for="item in state.modelExample"
					class="answerList-item1"
					:key="item.time"
					:class="item.type == 'answer' ? 'answerList-left1' : 'answerList-right1'"
				>
					<div class="answerList-title">
						<span class="answer-avatar">{{ item.type == "answer" ? "ans" : "que" }}</span>
						<span class="answer-time">{{ item.time }}</span>
					</div>
					<div class="answer-text">
						<span v-html="markdown.render(item.content)"></span>
					</div>
				</div>
				<div class="loading-box" v-show="state.loading">
					<span>正在回答，请稍等...</span>
				</div>
			</div>
			<div class="chat-send">
				<div class="send-btns">
					<div>
						<el-button
							type="primary"
							class="chat-btn"
							size="small"
							:icon="Delete"
							plain
							@click="clearModel"
							:disabled="state.loading"
							>清空</el-button
						>
						<el-button
							type="primary"
							class="chat-btn"
							size="small"
							:icon="Picture"
							plain
							v-show="state.modelType == 3"
							:disabled="state.loading"
							>图片上传</el-button
						>
						<el-button
							type="primary"
							class="chat-btn"
							size="small"
							:icon="UploadFilled"
							plain
							v-show="state.modelType == 8"
							:disabled="state.loading"
							>文件上传</el-button
						>
						<input
							type="file"
							id="fileInput"
							name="file"
							class="uploadInput"
							@change="fileChange"
							v-show="state.modelType == 3 || state.modelType == 8"
							:disabled="state.loading"
						/>
					</div>

					<el-button type="primary" class="chat-btn" size="small" @click="sendMsg" :disabled="state.loading"
						>发送<el-icon class="el-icon--right"><Position /></el-icon
					></el-button>
				</div>

				<el-input
					v-model="state.msg"
					:disabled="state.loading"
					:autosize="state.autosize"
					type="textarea"
					placeholder="请输入"
					class="chat-input"
					@keyup.enter="sendMsg"
				></el-input>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
import { API_URL } from "@/config/config";
import Message from "./components/Message.vue";
import Language from "./components/Language.vue";
import ThemeSetting from "./components/ThemeSetting.vue";
import Avatar from "./components/Avatar.vue";
import AssemblySize from "./components/AssemblySize.vue";
import { reactive } from "vue";
import { ElMessage } from "element-plus";
import { generateUUID } from "@/utils/util";
import MarkdownIt from "markdown-it";
import { Position, UploadFilled, Delete, Picture } from "@element-plus/icons-vue";
import {
	chatLLM,
	chatKnowledge,
	chatVisual,
	chatTextImg,
	chatEngine,
	chatCode,
	chatCodeChat,
	chatFile,
	chatFileUpload,
	chatFileUploadMinio
} from "@/api/modules/model/sensor";
const markdown = new MarkdownIt();
const state = reactive<any>({
	text: "### 您有一个办件需要处理\n - 发送时间：2020-02-21\n - 发送人：张三",
	loading: false,
	modelShow: false,
	autosize: { minRows: 2 },
	modelType: "1",
	modelExample: [
		{ type: "question", time: "2024/7/30 14:20:30", content: "凝思大模型AI助手，请问有什么可以帮您？" },
		{ type: "answer", time: "2024/7/30 14:20:32", content: "请输入您的问题..." }
	],
	modelOptions: [
		{ value: "1", label: "LLM对话" },
		{ value: "2", label: "知识库对话" },
		{ value: "3", label: "视觉对话" },
		{ value: "4", label: "智慧生图" },
		{ value: "5", label: "搜索引擎问答" },
		{ value: "6", label: "代码走读" },
		{ value: "7", label: "代码生成" },
		{ value: "8", label: "文件对话" }
	],
	msg: "",
	answerList: [
		// { type: 'question', time: '2024/7/30 14:20:30', content: '今天的日期今天的日期今天的日期今天的日期今天的日期今天的日期今天的日期今天的日期今天的日期'},
		// { type: 'answer',time: '2024/7/30 14:20:32', content: '今天的日期是2024年7月30日'},
		// { type: 'question', time: '2024/7/30 14:20:30', content: '今天的日期'},
		// { type: 'question', time: '2024/7/30 14:20:30', content: '今天的日期'},
	] // 答案列表
});
async function fileChange() {
	let inputFile: any = document.getElementById("fileInput");
	let file = inputFile.files[0];
	console.log(file);
	let type = file.type;
	if (state.modelType == 3) {
		// 只能上传图片
		if (type.indexOf("image/") == -1) {
			ElMessage.error("请选择图片上传！");
			return;
		}
	}
	let formData = new FormData();
	formData.append("uploadfile", file);
	formData.append("bucket", "ningsi");
	let uuidName = generateUUID() + file.name;
	formData.append("objectName", uuidName);
	state.loading = true;
	let result = await chatFileUploadMinio(formData);
	state.loading = false;
	// file.value = null
	if (state.modelType == 3) {
		// 视觉对话
		let obj1 = {
			type: "question",
			role: "user",
			content: result.result[1],
			imgUrl: result.result[1],
			time: getTime()
		};
		state.answerList.push(obj1);
	} else {
		uploadFile1(result.result[1]);
	}
}
async function uploadFile1(url) {
	let param = {
		files: [url]
	};
	state.loading = true;
	let result = await chatFileUpload(param);
	state.loading = false;
	console.log(result);
	let obj1 = {
		type: "question",
		role: "user",
		content: url,
		knowledge_id: result[0].data.id,
		time: getTime()
	};
	state.answerList.push(obj1);
}
function sendMsg() {
	if (!state.msg) return;
	if (state.modelType == 1) {
		sendMsgLLM();
	} else if (state.modelType == 2) {
		sendMsgKnowledge();
	} else if (state.modelType == 3) {
		sendMsgVisual();
	} else if (state.modelType == 4) {
		sendMsgTextImg();
	} else if (state.modelType == 5) {
		sendMsgEngine();
	} else if (state.modelType == 6) {
		sendMsgCode();
	} else if (state.modelType == 7) {
		sendMsgCodeChat();
	} else if (state.modelType == 8) {
		sendMsgFile();
	}
}
//文件对话
async function sendMsgFile() {
	if (!state.answerList.length) {
		ElMessage.error("请选择图片上传！");
		return;
	}
	let param = {
		query: state.msg,
		knowledge_id: state.answerList[state.answerList.length - 1].knowledge_id,
		top_k: 3,
		score_threshold: 1,
		history: state.answerList
	};
	state.loading = true;
	let result = await chatFile(param);
	state.loading = false;
	dealResult(result);
	let inputFile: any = document.getElementById("fileInput");
	inputFile.value = null;
}
//视觉对话
async function sendMsgVisual() {
	let urlArr = state.answerList.filter(e => {
		return e.imgUrl;
	});
	if (!urlArr.length) {
		ElMessage.error("请选择图片上传！");
		return;
	}
	let param = {
		query: state.msg,
		url: urlArr[urlArr.length - 1].imgUrl
	};
	state.loading = true;
	let result: any = await chatVisual(param);
	state.loading = false;
	// dealResult(result)
	let res = JSON.parse(result);
	console.log(res);
	let obj1 = {
		type: "question",
		role: "user",
		content: state.msg,
		time: getTime()
	};
	state.answerList.push(obj1);
	let obj2 = {
		type: "answer",
		role: "assistant",
		content: res.answer,
		time: getTime()
	};
	state.answerList.push(obj2);
	state.msg = "";
	let inputFile: any = document.getElementById("fileInput");
	inputFile.value = null;
	setScrollBottom();
}
//代码生成
async function sendMsgCodeChat() {
	let param = {
		query: state.msg,
		history: state.answerList,
		stream: false,
		coder_mode: "代码生成",
		coder_language: "Python"
	};
	state.loading = true;
	let result = await chatCodeChat(param);
	state.loading = false;
	dealResult(result);
}
//代码走读
async function sendMsgCode() {
	let param = {
		query: state.msg,
		history: state.answerList,
		stream: false,
		coder_mode: "代码走读"
	};
	state.loading = true;
	let result = await chatCode(param);
	state.loading = false;
	dealResult(result);
}
//搜索引擎问答
async function sendMsgEngine() {
	let param = {
		query: state.msg,
		history: state.answerList,
		stream: false,
		top_k: 3
	};
	state.loading = true;
	let result = await chatEngine(param);
	state.loading = false;
	dealResult(result);
}
//智慧生图
async function sendMsgTextImg() {
	let param = {
		query: state.msg
	};
	state.loading = true;
	let result: any = await chatTextImg(param);
	state.loading = false;
	let res = JSON.parse(result);
	let imgUrl = res.answer;
	if (imgUrl.indexOf("http://172.16.9.136:8501") > -1) {
		let url = res.answer.split("http://172.16.9.136:8501");
		imgUrl = "http://m.mdtu.com:28897" + url[1];
	}
	let obj1 = {
		type: "question",
		role: "user",
		content: state.msg,
		time: getTime()
	};
	state.answerList.push(obj1);
	let obj2 = {
		type: "answer",
		role: "assistant",
		content: "",
		time: getTime()
	};
	state.answerList.push(obj2);
	state.msg = "";
	setTimeout(() => {
		let leftDiv = document.getElementsByClassName("answerList-left");
		let leftLastDiv = leftDiv[leftDiv.length - 1];
		const image = document.createElement("img");
		image.src = imgUrl;
		image.width = 150;
		leftLastDiv.querySelector(".answer-text").querySelector("span").appendChild(image);
	}, 300);
	setScrollBottom();
}
//知识库对话
async function sendMsgKnowledge() {
	let param = {
		query: state.msg,
		history: state.answerList,
		stream: false,
		knowledge_base_name: "hongdian",
		top_k: 3,
		score_threshold: 1.0
	};
	state.loading = true;
	let result = await chatKnowledge(param);
	state.loading = false;
	dealResult(result);
}
//LLM对话
async function sendMsgLLM() {
	let param = {
		query: state.msg,
		history: state.answerList,
		stream: false
	};
	state.loading = true;
	let result = await chatLLM(param);
	state.loading = false;
	dealResult(result);
}
// 处理返回的结果
function dealResult(result) {
	if (result && result.indexOf("data:") > -1) {
		let msg = result.split("data:");
		let res = JSON.parse(msg[1]);
		console.log(res);
		let obj1 = {
			type: "question",
			role: "user",
			content: state.msg,
			time: getTime()
		};
		state.answerList.push(obj1);
		let obj2 = {
			type: "answer",
			role: "assistant",
			content: res.answer,
			time: getTime()
		};
		state.answerList.push(obj2);
		state.msg = "";
		setScrollBottom();
	}
}
// 滚动条到底部
function setScrollBottom() {
	setTimeout(() => {
		let el = document.getElementsByClassName("chat-content")[0];
		let h = el.scrollHeight;
		el.scrollTop = h;
	}, 200);
}
// 获取时间
function getTime() {
	// 创建一个 Date 对象
	let today = new Date();

	// 获取年、月、日、时、分、秒
	let year = today.getFullYear();
	let month = today.getMonth() + 1; // 月份是从 0 开始计数的，需要加1
	let day = today.getDate();
	let hours = today.getHours();
	let minutes = today.getMinutes();
	let seconds = today.getSeconds();

	// 格式化输出
	let formattedTime =
		year +
		"/" +
		(month < 10 ? "0" : "") +
		month +
		"/" +
		(day < 10 ? "0" : "") +
		day +
		" " +
		(hours < 10 ? "0" : "") +
		hours +
		":" +
		(minutes < 10 ? "0" : "") +
		minutes +
		":" +
		(seconds < 10 ? "0" : "") +
		seconds;

	return formattedTime;
}
// 关闭对话框
function closeModel() {
	state.modelShow = false;
	clearModel();
}
function showModel() {
	state.modelShow = true;
}
function clearModel() {
	state.msg = "";
	state.answerList = [];
	state.modelType = "1";
}
</script>
<style scoped lang="scss">
.tool-bar-ri {
	display: flex;
	align-items: center;
	justify-content: center;
	.header-icon {
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-right: 22px;
		> div {
			padding: 0 10px;
			:deep(i) {
				font-size: 20px;
				color: #777777;
			}
		}
		.model-ningsi {
			color: rgb(94 124 224 / 100%);
			cursor: pointer;
		}
	}
	.username {
		margin: 0 5px 0 0;
		font-size: 15px;
	}
}
.ningsiModel {
	position: fixed;
	top: 55px;
	right: 0;
	bottom: 0;
	z-index: 99;
	display: flex;
	flex-direction: column;
	width: 500px;
	background: #ffffff;
	border: 1px solid #dddddd;
	border-top: none;
	box-shadow: 0 5px 10px #dddddd;
	.ningsiModel-title {
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
		padding: 10px 20px;
		.title {
			font-size: 28px;
			font-weight: bold;
		}
		.close {
			font-weight: bold;
			cursor: pointer;
		}
		.chat-type {
			position: relative;
			top: 3px;
			left: -60px;
			display: flex;
			flex-direction: row;
			align-items: center;
			font-weight: bold;
		}
	}
	.chat-content {
		position: relative;
		display: flex;
		flex: 1;
		flex-direction: column;
		width: calc(100% - 40px);
		margin: 0 20px;
		overflow: auto;
		border: 1px solid #dddddd;
		border-radius: 4px;
		.answerList-item,
		.answerList-item1 {
			display: flex;
			flex-direction: column;
			margin: 10px 0;
			.answerList-title {
				position: relative;
				display: flex;
				flex-direction: row;
				align-items: center;
				height: 40px;
				.answer-avatar {
					width: 40px;
					height: 40px;
					line-height: 40px;
					text-align: center;
					border-radius: 20px;
				}
			}
		}
		.answerList-left,
		.answerList-left1 {
			.answer-avatar {
				margin-left: 10px;
				color: #ffffff;
				background: #2ebbd5;
			}
			.answer-time {
				margin-left: 10px;
			}
			.answer-text {
				margin: 0 50px;
				color: #ffffff;
				text-align: left;
				span {
					display: inline-block;
					padding: 0 10px;
					text-align: left;
					background: #2ebbd5;
					border-radius: 5px;
				}
			}
		}
		.answerList-right,
		.answerList-right1 {
			.answer-avatar {
				position: absolute;
				right: 10px;
				color: #ffffff;
				background: #1890ff;
			}
			.answer-time {
				position: absolute;
				right: 60px;
			}
			.answer-text {
				margin: 0 50px;
				color: #ffffff;
				text-align: right;
				span {
					display: inline-block;
					padding: 0 10px;
					text-align: left;
					background: #1890ff;
					border-radius: 5px;
				}
			}
		}
		.loading-box {
			position: absolute;
			bottom: 0;
			width: 100%;
			height: 28px;
			line-height: 28px;
			text-align: center;
		}
	}
	.chat-send {
		position: relative;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: space-between;
		width: calc(100% - 40px);
		padding: 0 20px;
		margin-bottom: 30px;
		.chat-input {
			width: 100%;
		}
		.send-btns {
			position: relative;
			display: flex;
			flex-direction: row;
			justify-content: space-between;
			width: 100%;
			padding-top: 20px;
			padding-bottom: 5px;
			.chat-btn {
			}
			.uploadInput {
				position: absolute;
				top: 22px;
				left: 76px;
				opacity: 0;
			}
		}
	}
}
</style>
